package com.kania.simpleemail.core;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Properties;

import javax.mail.Address;
import javax.mail.Authenticator;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.MimeUtility;

import com.kania.simpleemail.data.MailData;
import com.sun.mail.imap.IMAPFolder;

import android.os.Handler;
import android.util.Log;

/* Description
 * 이 class 는 singleton 디자인 패턴을 통하여 작성되었습니다.
 * 호출은 getInstance()를 통하여 이루어집니다.
 * 
 * 
 */

public class IMAP implements IMailReceiver {
	//singleton pattern
	private static IMAP IMAPInstance = new IMAP();
	
	private String sHost;
	private String sID;
	private String sPassword;
	
	private Store store;
	private Folder folder;
	
	private final String STRING_IMAP_NAME = "imap";
	private final String STRING_IMAP_SSL_PORT = "993";
	private final String STRING_SOCKETFACTORY_NAME = "javax.net.ssl.SSLSocketFactory";
	private final String STRING_SECURED_IMAP_NAME = "imaps";
	private final String STRING_DEFAULT_INBOX_NAME = "INBOX";	
	
	private final String sTag = "KANIA_LOG_CORE";
	
	private int nMaxMailNumber = 10; 
	
	private boolean isFullsyncCanceled;
	
	private Handler mHandler;

	private IMAP () {
		Log.d(sTag, "create singleton IMAP Instance");
	}
//	private IMAP(String _host, String _id, String _password) {
//		sHost = _host;
//		sID = _id;
//		sPassword = _password;
//	}
	
	public static IMAP getInstance () {
		return IMAPInstance;
	}
	
	public void setHost (String _host) {
		sHost = _host;
	}
	public void setID (String _id) {
		sID = _id;
	}
	public void setPassword (String _password) {
		sPassword = _password;
	}
	public void initIMAP (String _host, String _id, String _password) {
		setHost(_host);
		setID(_id);
		setPassword(_password);
	}
	
	//핸들러를 핸들링하기 위하여 ...?
	public void setHandler (Handler _handler) {
		mHandler = _handler;
	}
	
	@Override
	public void open()
			throws MessagingException {
		Properties props = new Properties();
		
		props.put("mail.transport", STRING_IMAP_NAME);
		props.put("mail.imap.host", sHost);
		props.put("mail.imap.port", STRING_IMAP_SSL_PORT);
		props.put("mail.imap.starttls.enable", "true");
		props.put("mail.imap.socketFactory.class", STRING_SOCKETFACTORY_NAME); 
		props.put("mail.imap.auth", "true");
		
		Log.d("KANIA_LOG_LIST", "In IMAP Auth = " + sID + " / " + sPassword);
		Authenticator auth = new MailAutentication(sID, sPassword);
		Session mailSession = Session.getInstance(props,auth);
		
		try {
			store = mailSession.getStore(STRING_SECURED_IMAP_NAME);
			store.connect(sHost, sID, sPassword);
			
			folder = store.getFolder(STRING_DEFAULT_INBOX_NAME);
			folder.open(Folder.READ_ONLY);
		} catch (Exception e) {
			Log.e("KANIA_LOG_CORE", "error in getting Store object");
			throw new MessagingException("error in store and folder");
		}
		
		Log.d("KANIA_LOG_CORE", "Success opening session");
	}

	@Override
	public void close() throws MessagingException {
		if (folder != null && folder.isOpen() == true) {
			folder.close(true);
		}
		if (store != null && store.isConnected() == true) {
			store.close();
		}
		
		Log.d("KANIA_LOG_CORE", "Success closing session");
	}

	@Override
	public Store getStore() throws MessagingException {
		if (store.isConnected() == false) {
			throw new MessagingException("Already closed store");
		}
		return store;
	}

	@Override
	public Folder getFolder() throws MessagingException {
		if (folder.isOpen() == false) {
			throw new MessagingException("Already closed folder");
		}
		return folder;
	}
	
	@Override
	public void getMessages (ArrayList<MailData> alMaildata, Handler mHandler) throws MessagingException {
		Message[] mails = null;
		int nMsgCount = 0;
		int nMailToRoad = 0;
		if (folder.isOpen() == true) {
			Log.d(sTag, "open Success!");
			nMsgCount = folder.getMessageCount();
			nMailToRoad = (nMsgCount > nMaxMailNumber)? nMsgCount-nMaxMailNumber: 0;
			Log.d(sTag, "count = " + nMsgCount);
			mails = folder.getMessages();
		}
		// 여기서 메일을 하나씩 받아오고 이를 handler로 notify한다
		for (int i = nMsgCount-1; i >= nMailToRoad; i--) {
			if (!mails[i].isSet(Flags.Flag.DELETED)) {
				//from
				String sFrom = "";
				Address[] adFrom = mails[i].getFrom();
				if (adFrom != null) {
					for(Address ad: adFrom) {
						String str = "";
						try {
							str = new String(MimeUtility.decodeText(ad.toString()));
						} catch (UnsupportedEncodingException e) {
							Log.e(sTag, "UnsupportedEncodingException in getting From data");
							e.printStackTrace();
						}
						sFrom += str + ",";
					}
				}
				//to
				String sTo = "";
				Address[] adTo = mails[i].getRecipients(Message.RecipientType.TO);
				if (adTo != null) {
					for(Address ad: adTo) {
						String str = "";
						try {
							str = new String(MimeUtility.decodeText(ad.toString()));
						} catch (UnsupportedEncodingException e) {
							Log.e(sTag, "UnsupportedEncodingException in getting From data");
							e.printStackTrace();
						}
						sTo += str + ",";
					}
				}
				//cc
				String sCC = "";
				Address[] adCC = mails[i].getRecipients(Message.RecipientType.CC);
				if (adCC != null) {
					for(Address ad: adCC) {
						String str = "";
						try {
							str = new String(MimeUtility.decodeText(ad.toString()));
						} catch (UnsupportedEncodingException e) {
							Log.e(sTag, "UnsupportedEncodingException in getting From data");
							e.printStackTrace();
						}
						sCC += str + ",";
					}
				}
				//bcc
				String sBCC = "";
				Address[] adBCC = mails[i].getRecipients(Message.RecipientType.BCC);
				if (adBCC != null) {
					for(Address ad: adBCC) {
						String str = "";
						try {
							str = new String(MimeUtility.decodeText(ad.toString()));
						} catch (UnsupportedEncodingException e) {
							Log.e(sTag, "UnsupportedEncodingException in getting From data");
							e.printStackTrace();
						}
						sBCC += str + ",";
					}
				}
				//date
				Calendar date = Calendar.getInstance();
				date.setTime(mails[i].getSentDate());
				//subject
				String subject = mails[i].getSubject();
				
				//create one maildata
				MailData md = new MailData(sFrom, sTo, sCC, sBCC, date, subject);
				
				//set uid
				md.setUID(((IMAPFolder) folder).getUID(mails[i]));

				alMaildata.add(md);
				mHandler.sendEmptyMessage(0);
				
				Log.d(sTag, "Mail Read = " + i + " : ");
				Log.d(sTag, "\tUID :" + md.getUID());
				Log.d(sTag, "\tFrom :" + sFrom);
				Log.d(sTag, "\tTo :" + sTo);
				Log.d(sTag, "\tCC :" + sCC);
				Log.d(sTag, "\tBCC :" + sBCC);
				Log.d(sTag, "\tDate :" + md.getMailDate());
				Log.d(sTag, "\tSubject :" + md.getMailSubject());
			} else {
				Log.d(sTag, "Mail Read = " + i + " : is deleted");
			}
		}
	}
	
	@Override
	public MailData getMessage () {
		MailData mailData = null;
		return mailData;
	}
	

}
